/*-----------------------------------------------------------------------------

 Copyright 2017 Hopsan Group

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.


 The full license is available in the file LICENSE.
 For details about the 'Hopsan Group' or information about Authors and
 Contributors see the HOPSANGROUP and AUTHORS files that are located in
 the Hopsan source code root directory.

-----------------------------------------------------------------------------*/

#ifndef HYDRAULICPISTON_HPP_INCLUDED
#define HYDRAULICPISTON_HPP_INCLUDED

#include <iostream>
#include "ComponentEssentials.h"
#include "ComponentUtilities.h"
#include "math.h"

//!
//! @file HydraulicPiston.hpp
//! @author Petter Krus <petter.krus@liu.se>
//  co-author/auditor **Not yet audited by a second person**
//! @date Tue 14 Apr 2015 10:01:19
//! @brief Hydraulic piston with two connection
//! @ingroup HydraulicComponents
//!
//==This code has been autogenerated using Compgen==
//from 
/*{, C:, HopsanTrunk, componentLibraries, defaultLibrary, Hydraulic, \
Volumes&Lines}/HydraulicPiston.nb*/

using namespace hopsan;

class HydraulicPiston : public ComponentC
{
private:
     double A1;
     double A2;
     double V01;
     double V02;
     double SL;
     double betae;
     double alpha;
     Port *mpP1;
     Port *mpP2;
     Port *mpPm1;
     int mNstep;
     //Port P1 variable
     double p1;
     double q1;
     double T1;
     double dE1;
     double c1;
     double Zc1;
     //Port P2 variable
     double p2;
     double q2;
     double T2;
     double dE2;
     double c2;
     double Zc2;
     //Port Pm1 variable
     double fm1;
     double xm1;
     double vm1;
     double cm1;
     double Zcm1;
     double eqMassm1;
//==This code has been autogenerated using Compgen==
     //inputVariables
     //outputVariables
     //InitialExpressions variables
     double c1f;
     double c2f;
     double cp1;
     double cp2;
     double cp1f;
     double cp2f;
     //LocalExpressions variables
     double V1;
     double V2;
     double qp1;
     double qp2;
     double c10;
     double c20;
     double cp10;
     double cp20;
     //Expressions variables
     //Port P1 pointer
     double *mpND_p1;
     double *mpND_q1;
     double *mpND_T1;
     double *mpND_dE1;
     double *mpND_c1;
     double *mpND_Zc1;
     //Port P2 pointer
     double *mpND_p2;
     double *mpND_q2;
     double *mpND_T2;
     double *mpND_dE2;
     double *mpND_c2;
     double *mpND_Zc2;
     //Port Pm1 pointer
     double *mpND_fm1;
     double *mpND_xm1;
     double *mpND_vm1;
     double *mpND_cm1;
     double *mpND_Zcm1;
     double *mpND_eqMassm1;
     //Delay declarations
//==This code has been autogenerated using Compgen==
     //inputVariables pointers
     //inputParameters pointers
     double *mpA1;
     double *mpA2;
     double *mpV01;
     double *mpV02;
     double *mpSL;
     double *mpbetae;
     double *mpalpha;
     //outputVariables pointers
     EquationSystemSolver *mpSolver;

public:
     static Component *Creator()
     {
        return new HydraulicPiston();
     }

     void configure()
     {
//==This code has been autogenerated using Compgen==

        mNstep=9;

        //Add ports to the component
        mpP1=addPowerPort("P1","NodeHydraulic");
        mpP2=addPowerPort("P2","NodeHydraulic");
        mpPm1=addPowerPort("Pm1","NodeMechanic");
        //Add inputVariables to the component

        //Add inputParammeters to the component
            addInputVariable("A1", "Piston area 1", "m2", 0.001,&mpA1);
            addInputVariable("A2", "Piston area 2", "m2", 0.001,&mpA2);
            addInputVariable("V01", "Dead Volume Piston 1", "m3", \
0.001,&mpV01);
            addInputVariable("V02", "Dead Volume Piston 2", "m3", \
0.001,&mpV02);
            addInputVariable("SL", "Stroke", "m", 0.5,&mpSL);
            addInputVariable("betae", "Bulk modulus", "Pa", 1.7e7,&mpbetae);
            addInputVariable("alpha", "Damp. factor", "1/s ", 0.,&mpalpha);
        //Add outputVariables to the component

//==This code has been autogenerated using Compgen==
        //Add constantParameters
     }

    void initialize()
     {
        //Read port variable pointers from nodes
        //Port P1
        mpND_p1=getSafeNodeDataPtr(mpP1, NodeHydraulic::Pressure);
        mpND_q1=getSafeNodeDataPtr(mpP1, NodeHydraulic::Flow);
        mpND_T1=getSafeNodeDataPtr(mpP1, NodeHydraulic::Temperature);
        mpND_dE1=getSafeNodeDataPtr(mpP1, NodeHydraulic::HeatFlow);
        mpND_c1=getSafeNodeDataPtr(mpP1, NodeHydraulic::WaveVariable);
        mpND_Zc1=getSafeNodeDataPtr(mpP1, NodeHydraulic::CharImpedance);
        //Port P2
        mpND_p2=getSafeNodeDataPtr(mpP2, NodeHydraulic::Pressure);
        mpND_q2=getSafeNodeDataPtr(mpP2, NodeHydraulic::Flow);
        mpND_T2=getSafeNodeDataPtr(mpP2, NodeHydraulic::Temperature);
        mpND_dE2=getSafeNodeDataPtr(mpP2, NodeHydraulic::HeatFlow);
        mpND_c2=getSafeNodeDataPtr(mpP2, NodeHydraulic::WaveVariable);
        mpND_Zc2=getSafeNodeDataPtr(mpP2, NodeHydraulic::CharImpedance);
        //Port Pm1
        mpND_fm1=getSafeNodeDataPtr(mpPm1, NodeMechanic::Force);
        mpND_xm1=getSafeNodeDataPtr(mpPm1, NodeMechanic::Position);
        mpND_vm1=getSafeNodeDataPtr(mpPm1, NodeMechanic::Velocity);
        mpND_cm1=getSafeNodeDataPtr(mpPm1, NodeMechanic::WaveVariable);
        mpND_Zcm1=getSafeNodeDataPtr(mpPm1, NodeMechanic::CharImpedance);
        mpND_eqMassm1=getSafeNodeDataPtr(mpPm1, \
NodeMechanic::EquivalentMass);

        //Read variables from nodes
        //Port P1
        p1 = (*mpND_p1);
        q1 = (*mpND_q1);
        T1 = (*mpND_T1);
        dE1 = (*mpND_dE1);
        c1 = (*mpND_c1);
        Zc1 = (*mpND_Zc1);
        //Port P2
        p2 = (*mpND_p2);
        q2 = (*mpND_q2);
        T2 = (*mpND_T2);
        dE2 = (*mpND_dE2);
        c2 = (*mpND_c2);
        Zc2 = (*mpND_Zc2);
        //Port Pm1
        fm1 = (*mpND_fm1);
        xm1 = (*mpND_xm1);
        vm1 = (*mpND_vm1);
        cm1 = (*mpND_cm1);
        Zcm1 = (*mpND_Zcm1);
        eqMassm1 = (*mpND_eqMassm1);

        //Read inputVariables from nodes

        //Read inputParameters from nodes
        A1 = (*mpA1);
        A2 = (*mpA2);
        V01 = (*mpV01);
        V02 = (*mpV02);
        SL = (*mpSL);
        betae = (*mpbetae);
        alpha = (*mpalpha);

        //Read outputVariables from nodes

//==This code has been autogenerated using Compgen==
        //InitialExpressions
        c1 = p1;
        c2 = p2;
        c1f = p1;
        c2f = p2;
        cp1 = p1;
        cp2 = p2;
        cp1f = p1;
        cp2f = p2;

        //LocalExpressions
        V1 = V01 + A1*limit(-xm1,0,SL);
        V2 = V02 + A2*limit(SL + xm1,0,SL);
        Zc1 = (betae*mTimestep)/((1 - alpha)*V1);
        Zc2 = (betae*mTimestep)/((1 - alpha)*V2);
        qp1 = A1*vm1;
        qp2 = -(A2*vm1);
        c10 = cp1 + 2*qp1*Zc1;
        c20 = cp2 + 2*qp2*Zc2;
        cp10 = c1 + 2*q1*Zc1;
        cp20 = c2 + 2*q2*Zc2;

        //Initialize delays


        simulateOneTimestep();

     }
    void simulateOneTimestep()
     {
        //Read variables from nodes
        //Port P1
        p1 = (*mpND_p1);
        q1 = (*mpND_q1);
        dE1 = (*mpND_dE1);
        //Port P2
        p2 = (*mpND_p2);
        q2 = (*mpND_q2);
        dE2 = (*mpND_dE2);
        //Port Pm1
        fm1 = (*mpND_fm1);
        xm1 = (*mpND_xm1);
        vm1 = (*mpND_vm1);
        eqMassm1 = (*mpND_eqMassm1);

        //Read inputVariables from nodes

        //Read inputParameters from nodes
        A1 = (*mpA1);
        A2 = (*mpA2);
        V01 = (*mpV01);
        V02 = (*mpV02);
        SL = (*mpSL);
        betae = (*mpbetae);
        alpha = (*mpalpha);

        //LocalExpressions
        V1 = V01 + A1*limit(-xm1,0,SL);
        V2 = V02 + A2*limit(SL + xm1,0,SL);
        Zc1 = (betae*mTimestep)/((1 - alpha)*V1);
        Zc2 = (betae*mTimestep)/((1 - alpha)*V2);
        qp1 = A1*vm1;
        qp2 = -(A2*vm1);
        c10 = cp1 + 2*qp1*Zc1;
        c20 = cp2 + 2*qp2*Zc2;
        cp10 = c1 + 2*q1*Zc1;
        cp20 = c2 + 2*q2*Zc2;

          //Expressions
          c1f = (1. - alpha)*c10 + alpha*c1f;
          cp1f = (1. - alpha)*cp10 + alpha*cp1f;
          c2f = (1. - alpha)*c20 + alpha*c2f;
          cp2f = (1. - alpha)*cp20 + alpha*cp2f;
          c1 = c1f;
          cp1 = cp1f;
          c2 = c2f;
          cp2 = cp2f;
          cm1 = A1*cp1 - A2*cp2;
          Zcm1 = Power(A1,2)*Zc1 + Power(A2,2)*Zc2;

        //Calculate the delayed parts


        //Write new values to nodes
        //Port P1
        (*mpND_T1)=T1;
        (*mpND_c1)=c1;
        (*mpND_Zc1)=Zc1;
        //Port P2
        (*mpND_T2)=T2;
        (*mpND_c2)=c2;
        (*mpND_Zc2)=Zc2;
        //Port Pm1
        (*mpND_cm1)=cm1;
        (*mpND_Zcm1)=Zcm1;
        //outputVariables

        //Update the delayed variabels

     }
    void deconfigure()
    {
        delete mpSolver;
    }
};
#endif // HYDRAULICPISTON_HPP_INCLUDED
